package DyingBaby.backend.tm;

import DyingBaby.common.Error;
import DyingBaby.utils.Panic;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

/**
 * @author gumaomao
 */
public interface TransactionManager {

    /**
     * 开启一个新事务
     *
     * @return 新事务的事务 ID
     */
    long begin();

    /**
     * 提交一个事务
     * @param xid 要提交的事务的 ID
     */
    void commit(long xid);

    /**
     * 取消一个事务
     * @param xid 要取消的事务的 ID
     */
    void abort(long xid);

    /**
     * 查询一个事务的状态是否是正在进行的状态
     *
     * @param xid 要查询状态的事务的 ID
     * @return 如果事务处于活动状态，返回 true；否则返回 false
     */
    boolean isActive(long xid);

    /**
     * 查询一个事务的状态是否是已提交
     *
     * @param xid 要查询状态的事务的 ID
     * @return 如果事务已经提交，返回 true；否则返回 false
     */
    boolean isCommitted(long xid);

    /**
     * 查询一个事务的状态是否是已取消
     * @param xid 要查询状态的事务的 ID
     * @return 如果事务已经取消，返回 true；否则返回 false
     */
    boolean isAborted(long xid);

    /**
     * 关闭 TM
     */
    void close();


    /**
     * 创建一个新的事务管理器实例（新建XID文件）
     * @param path XID文件的存储路径
     * @return 事务管理器实例
     */
    public static TransactionManagerImpl create(String path) {
        // 创建XID文件对象
        File f = new File(path+TransactionManagerImpl.XID_SUFFIX);
        // 确保父目录存在
        File parent = f.getParentFile();
        if(parent != null && !parent.exists()) {
            if(!parent.mkdirs()) {
                Panic.panic(Error.FileCannotRWException);
            }
        }
        // 创建新的XID文件
        try {
            if(!f.createNewFile()) {
                Panic.panic(Error.FileExistsException);
            }
        } catch (Exception e) {
            Panic.panic(e);
        }
        // 检查文件读写权限
        if(!f.canRead() || !f.canWrite()) {
            Panic.panic(Error.FileCannotRWException);
        }

        FileChannel fc = null;
        RandomAccessFile raf = null;
        try {
            // 以读写模式打开文件
            raf = new RandomAccessFile(f, "rw");
            fc = raf.getChannel();
        } catch (FileNotFoundException e) {
            Panic.panic(e);
        }

        // 写入空的XID文件头（初始化文件）
        ByteBuffer buf = ByteBuffer.wrap(new byte[TransactionManagerImpl.LEN_XID_HEADER_LENGTH]);
        try {
            fc.position(0);
            fc.write(buf);
        } catch (IOException e) {
            Panic.panic(e);
        }

        // 创建并返回事务管理器实现实例
        return new TransactionManagerImpl(raf, fc);
    }

    /**
     * 打开已存在的事务管理器（基于现有的XID文件）
     * @param path XID文件的存储路径
     * @return 事务管理器实例
     */
    public static TransactionManagerImpl open(String path) {
        // 检查XID文件是否存在
        File f = new File(path+TransactionManagerImpl.XID_SUFFIX);
        if(!f.exists()) {
            Panic.panic(Error.FileNotExistsException);
        }
        // 检查文件读写权限
        if(!f.canRead() || !f.canWrite()) {
            Panic.panic(Error.FileCannotRWException);
        }

        FileChannel fc = null;
        RandomAccessFile raf = null;
        try {
            // 以读写模式打开文件
            raf = new RandomAccessFile(f, "rw");
            fc = raf.getChannel();
        } catch (FileNotFoundException e) {
            Panic.panic(e);
        }

        // 创建并返回事务管理器实现实例
        return new TransactionManagerImpl(raf, fc);
    }


}
